import pickle
import cv2
import face_recognition
import time

import importlib
import sys
from dao.index import LoginSchema
from utils.json import JSONHandler
import base64
import io
from PIL import Image
import numpy as np

if sys.getdefaultencoding() != 'utf-8':
    importlib.reload(sys)
    sys.setdefaultencoding('utf-8')


class FaceRecognition:
    def __init__(self, target_name_count=2, timeout_seconds=60):
        self.target_name_count = target_name_count
        self.recognized_names = set()
        self.ans = set()  # 使用集合而不是列表
        self.known_face_encodings = []
        self.known_face_labels = []
        self.timeout_seconds = timeout_seconds
        self.start_time = time.time()
        self.json = JSONHandler("./config/cache.json")


    def add_face(self):
        user = LoginSchema().get_student(self.json.read()['user_id'])
        # 从数据库读取base64字符串
        auth_img_base64 = user['auth_img']
        
        try:
            # 将base64字符串解码为字节数据
            image_bytes = base64.b64decode(auth_img_base64)
            
            # 将字节数据转换为PIL图像对象
            image = Image.open(io.BytesIO(image_bytes))
            
            # 将PIL图像转换为numpy数组（face_recognition需要的格式）
            image_np = np.array(image)
            
            # 生成人脸编码
            face_encodings = face_recognition.face_encodings(image_np)
            
            if len(face_encodings) == 0:
                raise ValueError("未在图像中检测到人脸")
                
            # 假设每张图片只录入一个人脸，取第一个编码
            encoding = face_encodings[0]
            
            self.known_face_encodings.append(encoding)
            self.known_face_labels.append(user['en_name'])
            
        except base64.binascii.Error:
            raise ValueError("无效的base64图像格式")
        except IOError:
            raise ValueError("无法解析图像数据")
        


    def run(self, stu_name):
        # 打开摄像头
        cap = cv2.VideoCapture(0)

        while True:
            # 读取摄像头帧
            ret, frame = cap.read()

            # 转换颜色空间
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

            # 检测当前帧中的人脸
            face_locations = face_recognition.face_locations(rgb_frame)
            face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)

            # 存储当前帧的所有人脸标签
            frame_face_labels = set()  # 使用集合而不是列表

            for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
                # 在人脸周围绘制矩形框
                cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)

                # 尝试匹配人脸
                matches = face_recognition.compare_faces(self.known_face_encodings, face_encoding, tolerance=0.5)
                name = "Unknown"

                # 如果有匹配，则使用第一个匹配的标签
                if True in matches:
                    first_match_index = matches.index(True)
                    name = self.known_face_labels[first_match_index]

                # 在矩形框上方显示匹配的标签
                # cv2.putText(frame, name, (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
                cv2.putText(frame, name, (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2, cv2.LINE_AA)

                # 添加当前人脸的标签到集合
                frame_face_labels.add(name)
                if name == stu_name:
                    self.ans.add(name)

            # 显示结果
            cv2.imshow('检测窗口', frame)

            if(time.time() - self.start_time > self.timeout_seconds):
                break

            # 按 'q' 键退出循环
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        # 释放摄像头并关闭窗口
        cap.release()
        cv2.destroyAllWindows()
        return self.ans

# # 示例用法：
# face_recognition_instance = FaceRecognition(target_name_count=2, timeout_seconds=20)

# # 添加已知人脸
# face_recognition_instance.add_face('obama.jpg', 'obama')
# face_recognition_instance.add_db('biden.jpg', 'biden')

# 运行人脸识别
# face_recognition_instance.run()
